package listener

import (
	"encoding/json"
	"github.com/sirupsen/logrus"
	"hcy-api/lib/utils"
	"hcy-api/structs/constant"
	"hcy-api/structs/idp"
	"hcy-api/structs/tables"
	"idp/global"
	"idp/repository"
)

// Full 全量信息，一般设备第一次加入列表是发送改指令
func Full(clientId int64) {
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "abstract.exe", nil); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}
	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "vap.exe", []string{"-al"}); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}
	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "board.exe", []string{"-type=base"}); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}

	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "cpu.exe", nil); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}

	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "disk.exe", []string{"-type=physics"}); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}

	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "memory.exe", nil); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}

	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "network.exe", []string{"-n"}); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}

	}()
	go func() {
		if err := SendInstruct(clientId, constant.ExecutePlugin, "process.exe", []string{"-l"}); err != nil {
			logrus.Errorf("发送指令时发生错误：%v", err)
		}
	}()
}

// RemoveCatchInstruct 移除某个指令，
func RemoveCatchInstruct(clientId int64, inst idp.PluginInstruct) {
	pm := global.GetClientInstructCatch(clientId)
	delete(pm, InstructionUtils.GetCatchKey(inst))
	global.SetClientInstructCatch(clientId, pm)
}

// InsertCatchInstruct 插入指令
func InsertCatchInstruct(clientId int64, inst idp.PluginInstruct) {
	pm := global.GetClientInstructCatch(clientId)
	pm[InstructionUtils.GetCatchKey(inst)] = inst
	global.SetClientInstructCatch(clientId, pm)
}

// PrepareInstruct 准备任务指令,尽量在协程中调用它
func PrepareInstruct(clientId int64) {
	var err error
	// 分为 执行任务、升级任务、下载客户端任务等等

	// 执行任务指令直接写入缓存 global.ClientInstructCatch 中
	tasks, err := repository.TaskRepository.FindAll()
	if err != nil {
		logrus.Error(err)
		return
	}
	for _, v := range tasks {
		PrepareInstructForTask(v, clientId)
	}
}

// PrepareInstructForTask 准备基于任务的指令
func PrepareInstructForTask(task tables.IdpTask, clientId int64) {
	var (
		isSend bool // 该任务是否对当前客户端生效
		err    error
	)
	switch task.TaskRank {
	case tables.IdpTaskRankForFull:
		isSend = true
	case tables.IdpTaskRankForBranch:
		ids := make([]int64, 0)
		err = json.Unmarshal([]byte(task.MapIds), &ids)
		if err != nil {
			logrus.Error(err)
		}
		var branchId int64
		branchId, err = repository.BranchRepository.FindClientMapBranchId(clientId)
		if err != nil {
			logrus.Error(err)
		}
		if utils.Contains(ids, branchId) {
			isSend = true
		}
	case tables.IdpTaskRankForClient:
		ids := make([]int64, 0)
		err = json.Unmarshal([]byte(task.MapIds), &ids)
		if err != nil {
			logrus.Error(err)
		}
		if utils.Contains(ids, clientId) {
			isSend = true
		}
	}
	// 符合发送要求
	if isSend {
		// 检查客户端是否已经存在任务ok记录
		var ok bool
		ok, err = repository.TaskRepository.FindTaskResultIsOk(task.Id, clientId)
		if err != nil {
			logrus.Error(err)
		}
		if !ok {
			var inst idp.PluginInstruct
			inst, err = InstructionUtils.TaskForFileAndProcess(task)
			if err != nil {
				logrus.Error(err)
			} else {
				InsertCatchInstruct(clientId, inst)
			}
		}
	}
}
